﻿#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <limits.h>
#if defined(WIN32) || defined(WIN64)
#include "windows.h"
#endif

#include "define.h"
#include <curl/curl.h>
#include "iota.h"
#include "cjson/cJSON.h"
#include "zlog.h"
#include "iniparser.h"
#include "http.h"
#include "BussinessTerminalManage.h"
#include "iota.h"
#include "microApp.h"
#include "common.h"

char LogLevel[32];
dictionary *ini;
dictionary *iniMqtt;
dictionary *iniRule;
char path[256];
extern Snowflake sf;
extern ST_MODEL_CTL g_st_model_ctl;

void wiat_for_signal()
{
	printf("wiat_for_signal...\n");
	sleep(60);
}

void *Security_thread(void *param)
{
	dzlog_info("Security_thread start...");
	pthread_detach(pthread_self());
	char path[256] = {0};

	sprintf(path, "./conf/EagleEyeSMG.ini");
	while (1)
	{
		{
			// 动态修改系统日志等级 start
			dictionary *ini = iniparser_load(path);
			if (ini == NULL)
			{
			}
			else
			{
				char *LogLeveltmp = iniparser_getstring(ini, "syslog:level", NULL);
				if (LogLeveltmp == NULL)
				{
					setlogmask(LOG_UPTO(LOG_WARNING));
				}
				else
				{
					if (strcmp(LogLevel, LogLeveltmp) != 0)
					{
						strcpy(LogLevel, LogLeveltmp);
						if (strcmp(LogLevel, "LOG_EMERG") == 0)
						{
							setlogmask(LOG_UPTO(LOG_EMERG));
						}
						else if (strcmp(LogLevel, "LOG_ALERT") == 0)
						{
							setlogmask(LOG_UPTO(LOG_ALERT));
						}
						else if (strcmp(LogLevel, "LOG_CRIT") == 0)
						{
							setlogmask(LOG_UPTO(LOG_CRIT));
						}
						else if (strcmp(LogLevel, "LOG_ERR") == 0)
						{
							setlogmask(LOG_UPTO(LOG_ERR));
						}
						else if (strcmp(LogLevel, "LOG_WARNING") == 0)
						{
							setlogmask(LOG_UPTO(LOG_WARNING));
						}
						else if (strcmp(LogLevel, "LOG_NOTICE") == 0)
						{
							setlogmask(LOG_UPTO(LOG_NOTICE));
						}
						else if (strcmp(LogLevel, "LOG_INFO") == 0)
						{
							setlogmask(LOG_UPTO(LOG_INFO));
						}
						else if (strcmp(LogLevel, "LOG_DEBUG") == 0)
						{
							setlogmask(LOG_UPTO(LOG_DEBUG));
						}
						else
						{
							setlogmask(LOG_UPTO(LOG_WARNING));
						}
					}
				}
				
			}
			iniparser_freedict(ini);
			// 动态修改系统日志等级 end
		}

		{
			// 检查是否有对应目录，并创建
			struct stat st = {0};
			if (stat("/userdata/security/", &st) == -1)
			{
				umask(0);
				mkdir("/userdata/security/", 0755);
			}
			if (stat("/security", &st) == -1)
			{
				umask(0);
				mkdir("/security/", 0755);
			}
			if (stat("/security/systemcertificates", &st) == -1)
			{
				umask(0);
				mkdir("/security/systemcertificates", 0755);
			}
			if (stat("/security/.certificate/", &st) == -1)
			{
				umask(0);
				mkdir("/security/.certificate/", 0700);
			}
			if (stat("/etc/config", &st) == -1)
			{
				umask(0);
				mkdir("/etc/config/", 0755);
			}

			if (stat("/PowerHarmony", &st) == -1)
			{
				umask(0);
				mkdir("/PowerHarmony", 0755);
			}
			if (stat("/PowerHarmony/SMC", &st) == -1)
			{
				umask(0);
				mkdir("/PowerHarmony/SMC", 0755);
			}
			if (stat("/PowerHarmony/SMC/Connection/", &st) == -1)
			{
				umask(0);
				mkdir("/PowerHarmony/SMC/Connection/", 0755);
			}
			if (stat("/PowerHarmony/SMC/sec/", &st) == -1)
			{
				umask(0);
				mkdir("/PowerHarmony/SMC/sec/", 0777);
			}
			system("chmod 777 -R /PowerHarmony/SMC/sec/");
			if (stat("/PowerHarmony/SMC/Config/", &st) == -1)
			{
				umask(0);
				mkdir("/PowerHarmony/SMC/Config/", 0755);
			}
			if (stat("/PowerHarmony/SMC/app", &st) == -1)
			{
				umask(0);
				mkdir("/PowerHarmony/SMC/app", 0755);
			}
			if (stat("/PowerHarmony/SMC/app/EagleEyeSMG/", &st) == -1)
			{
				umask(0);
				mkdir("/PowerHarmony/SMC/app/EagleEyeSMG/", 0755);
			}
			if (stat("/PowerHarmony/SMC/sec/cnX509/", &st) == -1)
			{
				umask(0);
				mkdir("/PowerHarmony/SMC/sec/cnX509/", 0755);
			}

		}

		{
			tosetroute();
		}
		sleep(60);
	}
}

int get_current_md5(char* md5_buf) {
	FILE* fp = popen("iptables -S | md5sum | cut -d' ' -f1", "r");
	if (!fp) return -1;

	// 读取纯粹的MD5值（32字符）
	if (fgets(md5_buf, 33, fp) == NULL) {
		pclose(fp);
		return -1;
	}

	pclose(fp);

	// 去除可能的换行符
	md5_buf[strcspn(md5_buf, "\n")] = 0;

	return 0;
}

void *self_checking_thread(void *param)
{
	dzlog_info("self_checking_thread start...");
	pthread_detach(pthread_self());
	pthread_setname_np(pthread_self(), "lsc_test");

	int result = system("ps -ef");
	if (result == 0)
	{
		printf("ps -ef ok\n");
		dzlog_info("ps -ef ok");
	}
	else
	{
		printf("ps -ef not found \n");
		dzlog_info("ps -ef not found");
	}

	FILE *fp = NULL;
	char buf[256];
	int s4g = 0;
	if ((fp = popen("wwan at send AT+CGMI dev ppp0", "r")) == NULL)
	{
		dzlog_info("_4gPopenCmd start popen error");
	}
	else
	{
		while (fgets(buf, 255, fp) != NULL)
		{
			char* p = strstr(buf, "OK");
			if (p)
			{
				s4g = 1;
				dzlog_info("wwan at send AT+CGMI dev ppp0 ok");
			}
		}
	}
	if (s4g)
	{
		g_st_model_ctl._4gModules = 1;
	}
	else
	{
		g_st_model_ctl._4gModules = 0;
	}
	if (fp != NULL)
	{
		fclose(fp);
	}
	else
	{
		dzlog_info("fp is NULL");
	}
	

	result = system("appm -V");
	if (result == 0)
	{
		printf("appm -V [ok]\n");
		dzlog_info("appm -V [ok]");
		g_st_model_ctl.appModules = 1;
	}
	else
	{
		printf("appm -V not found\n");
		dzlog_info("appm -V not found");
		g_st_model_ctl.appModules = 0;
	}
	dzlog_info("_4gModules[%d] appModules[%d]", g_st_model_ctl._4gModules, g_st_model_ctl.appModules);

	sleep(30);
	char current_md5[33] = { 0 };
	char last_md5[33] = { 0 };
	if (get_current_md5(last_md5) == 0) {
		printf("初始MD5: %s\n", last_md5);
	}

	while (1) {
		if (get_current_md5(current_md5) == 0) {
			if (strcmp(current_md5, last_md5) != 0) {
				dzlog_info("iptables change");
				system("iptables -S > ./conf/iptables_bak.txt");
				strcpy(last_md5, current_md5);
			}
		}
		else {
			printf("获取MD5失败\n");
		}
		sleep(5);
	}

	//char uuid[64] = { 0 };
	//while (true)
	//{
	//	memset(uuid,0,64);
	//	GF_GetGUID(uuid);
	//	dzlog_info("uuid[%s]", uuid);
	//}

}

void *powerHarmony_checking_thread(void *param)
{
	dzlog_info("powerHarmony_checking_thread start");
	pthread_detach(pthread_self());		
	const char *cmd = "sim_message";

	char *json_string = NULL;
	int ii = 0;
	for (ii = 0; ii < 4; ii++)
	{
		int ret = popen_get_json(&json_string, cmd);
		if (ret == 0)
		{
			// 解析 JSON 字符串
			cJSON *json_result = NULL;
			json_result = cJSON_Parse(json_string);
			if (!json_result)
			{
				dzlog_info("Error: \"_4gModules\" is not a valid JSON\n");
				free_s(json_string);
				if (ii == 3)
				{
					g_st_model_ctl._4gModules = 0;
					return -1;
				}
				sleep(1);
				continue;
			}
			// 检查support4G键是否true
			cJSON *item  = cJSON_GetObjectItem(json_result, "support4G");
			if (item && cJSON_IsBool(item))
			{
				dzlog_info("support4G444:%d\n",cJSON_IsTrue(item));
				if(!cJSON_IsTrue(item))
				{
					g_st_model_ctl._4gModules = 0;
				}else{
					dzlog_info("support4G22:%d\n",cJSON_IsTrue(item));
					g_st_model_ctl._4gModules = 1;
				}
			}else
			{
				dzlog_info("support4G：null:\n");
				// g_st_model_ctl._4gModules = 0; //兼容老设备，没有support4G字段
			}
			cJSON_Delete(json_result);
			free_s(json_string);
			break;
		}
	}
}

void iotInfo_thread()
{
	dzlog_info("iotInfo_thread start");
	check_and_report_iot_changes();
}

/// @brief 信号处理函数
/// @param signo 信号
void sig_handler(int signo)
{
	setstatus(0);
	system("iptables -S > ./conf/iptables_bak.txt");
	dzlog_info("sig_handler");
	FILE *fp = fopen("/tmp/EagleEyeSMG.pid", "w");
	if (fp == NULL)
	{
		dzlog_error("open file error");
		exit(1);
	}

	//信号分类总结
	//信号		编号	类型		默认行为		可否捕获
	//SIGINT	2		用户中断	终止			是
	//SIGILL	4		程序错误	终止 + 核心转储	是
	//SIGFPE	8		程序错误	终止 + 核心转储	是
	//SIGSEGV	11		程序错误	终止 + 核心转储	是
	//SIGTERM	15		终止请求	终止			是
	//SIGABRT	6		程序错误	终止 + 核心转储	是
	if (signo == SIGINT)//pee有测试出来
	{
		/*
		1.用户在终端按下 Ctrl+C
		2.键盘中断请求
		*/
		fprintf(fp, "interrupt|%d", time(NULL));
		dzlog_info("sig_handler SIGINT");			
	}
	else if (signo == SIGILL)//未测试触发过
	{
		/*
		1.执行非法或未定义的机器指令
		2.代码损坏或错误的函数指针调用
		3.硬件不支持的指令
		*/
		fprintf(fp, "codedump|%d", time(NULL));
		dzlog_info("sig_handler SIGILL");
	}
	else if (signo == SIGFPE)
	{
		/*
		1.除以零
		2.浮点溢出/下溢
		3.无效的浮点操作
		*/
		fprintf(fp, "codedump|%d", time(NULL));
		dzlog_info("sig_handler SIGFPE");
	}
	else if (signo == SIGSEGV)//pee已触发，触发测试代码int* ptr = NULL;*ptr = 42;
	{
		/*
		1.访问无效内存地址
		2.访问只读内存区域
		3.栈溢出
		4.使用已释放的内存
		*/
		fprintf(fp, "codedump|%d", time(NULL));
		dzlog_info("sig_handler SIGSEGV");
	}
	else if (signo == SIGTERM)//
	{
		/*
		1.kill 命令的默认信号
		2.系统关闭(系统重启)
		3.进程管理器请求终止
		*/
		fprintf(fp, "interrupt|%d", time(NULL));
		dzlog_info("sig_handler SIGTERM");
	}
	else if (signo == SIGABRT)//pee没测试触发出来
	{
		/*
		1.调用 abort() 函数
		2.断言失败 (assert)
		3.内存分配错误等
		*/
		fprintf(fp, "codedump|%d", time(NULL));
		dzlog_info("sig_handler SIGABRT");
	}
	
	fclose(fp);
	exit(signo);
}
 
int main(int argc, char **argv)
{
	int ret = 0;
 
	memset(LogLevel, 0, sizeof(LogLevel));
	sprintf(LogLevel, "LOG_WARNING");

	// 日志模块初始化
	dzlog_init("./conf/zlog.conf", "GetIoT");

	if (snowflake_init(&sf, 1) != 0) {
		fprintf(stderr, "Invalid worker ID. Must be 0-%lu\n", MAX_WORKER_ID);
	}

	FILE* file1 = fopen("/PowerHarmony/SMC/app/EagleEyeSMG/conf/status", "w");
	if (file1 != NULL)
	{
		// 写入内容
		fprintf(file1, "0");
		// 关闭文件
		fclose(file1);
	}

	g_st_model_ctl.appModules = 0;
	g_st_model_ctl._4gModules = 1;
	// 开启摄像头自检，检查是否有4G模块
	pthread_t powerHarmony_checking;
	ret = pthread_create(&powerHarmony_checking, NULL, powerHarmony_checking_thread, NULL);
	if (ret != 0)
	{
		dzlog_error("pthread_create powerHarmony_checking_thread error\n");
	}

	// 启动线程，拉起安全组件 start
	pthread_t tid_Security;
	ret = pthread_create(&tid_Security, NULL, Security_thread, NULL);
	if (ret != 0)
	{
		dzlog_error("pthread_create Security_thread error\n");
		// return;
	}

	pthread_t tid_iotInfo;
	ret = pthread_create(&tid_iotInfo, NULL, iotInfo_thread, NULL);
	if (ret != 0)
	{
		dzlog_error("netTest_thread keep_alive_thread error\n");
		return;
	}

	// 启动线程，拉起安全组件 end
	// ini配置文件初始化
	// iniparser 的一条原则是 section 和 key 大小写无关，写入的字符串全部小写化，取出的字符串也全部小写化
	// iniparser注释以英文分号开头（;这是配置文件注释,而不是#）
 
	if (config_init(&ini, &iniMqtt, &iniRule))
	{
		dzlog_error("config_init error\n");
	}
	else
	{
		dzlog_info("config_init succ");
	}

	struct sigaction sa;
	sa.sa_handler = sig_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;

	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGILL, &sa, NULL);
	sigaction(SIGFPE, &sa, NULL);
	sigaction(SIGSEGV, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGABRT, &sa, NULL);

	// 启动线程，拉起安全组件 end

	// 管理模块
	// 1可适配接入外部组件，例如安全组件；
	// 2内部功能初始化，并设置全局回调函数（登录、发送消息、接收消息、功能处理...）；
	// 3管理模块，初始化各个协议对象；
	// 4数据内存模块，redis/db/队列。
	manage_control();
	// 程序启动时调用需要执行的shell
	commond_init_run();
	//   调度层:可兼容mqtt、rtp、rtsp、GB、私有协议
	dispach_proc();
	
	// 等待信号并处理
	while (1)
	{
		wiat_for_signal();
	}

	iniparser_freedict(ini);
	iniparser_freedict(iniMqtt);
	iniparser_freedict(iniRule);
	freeConfTerminalIni();
	manage_free();

	return 0;
}
